//
//  ZDDXOperationsPrivate.h
//  Part of Z-Way.C library
//
//  Created by Pavel Kulaha.
//  Based on Z-Way source code written by Christian Paetz and Poltorak Serguei
//
//  Copyright (c) 2024 Z-Wave.Me
//  All rights reserved
//  info@z-wave.me
//
//  This source file is subject to the terms and conditions of the
//  Z-Wave.Me Software License Agreement which restricts the manner
//  in which it may be used.
//

#ifndef zddx_operations_private_h
#define zddx_operations_private_h

#include "ZDDXml.h"
#include "ZStreamPrivate.h"
#include "ZMalloc.h"

#define Z_ZDDX_OPERATIONS_PATH "zddx"

typedef struct _ZddxOperationsAttributes_s
{
    ZWDWORD id;
    ZWDWORD device_id;
#if defined(__ZWAY_SAVE_XML__) && defined(__ZWAY_SAVE_CBOR__)
    ZEncoderDecoderType_t type;
#endif
#if defined(__ZWAY_SAVE_ONE_FILE__) && defined(__ZWAY_SAVE_SEPARATE_DEVICE_FILES__)
    ZWBOOL separate:1;
#endif
    union
    {
        struct
        {
            ZWBOOL valid_prefix:1;
            ZWBOOL valid_separate:1;
            ZWBOOL valid_type:1;
            ZWBOOL valid_device_id:1;
            ZWBOOL prefix_root:1;
        };
        ZWBOOL valid;
    };
} _ZddxOperationsAttributes_t;

typedef struct _ZddxOperationsConfigFunctions_s
{
#if defined(__ZWAY_SAVE_ONE_FILE__) && defined(__ZWAY_SAVE_XML__) && !defined(__ZWAY_STATIC_CONFIGURATION__)
    void (*pre_load_one_file)(void *, ZWCSTR);
#endif
#if defined(__ZWAY_SAVE_SEPARATE_DEVICE_FILES__)
    ZWBOOL (*device_is_valid)(void *, ZWDWORD);
#endif
    ZWDWORD (*get_id)(void *);
    ZEncoderDecoderStatus_t (*load_controller)(void *, ZDecoder_t *);
    ZEncoderDecoderStatus_t (*load_device)(void *, ZDecoder_t *, ZWDWORD);
    ZEncoderDecoderStatus_t (*save_controller)(void *, ZEncoder_t *);
    ZEncoderDecoderStatus_t (*save_device)(void *, ZEncoder_t *, ZWDWORD, void *);
    ZWDWORD (*device_iterator_get_id)(void *);
    void *(*device_get_iterator)(void *);
    void *(*device_next_iterator)(void *);
} _ZddxOperationsConfigFunctions_t;

typedef struct _ZddxOperationsConfigCtx_s
{
    ZDataRootObject data_root;
    ZWSTR config_dir;
    ZWCSTR prefix;
    const _ZddxOperationsConfigFunctions_t *functions;
    void *arg;
    size_t length_config_dir;
#if defined(__ZWAY_SAVE_XML__) && defined(__ZWAY_SAVE_CBOR__)
    ZEncoderDecoderType_t type;
#endif
    _ZddxOperationsAttributes_t restore_attributes;
    ZWBOOL loaded;
#if defined(__ZWAY_SAVE_ONE_FILE__) && defined(__ZWAY_SAVE_SEPARATE_DEVICE_FILES__)
    ZWBOOL separate;
#endif
} _ZddxOperationsConfigCtx_t;

typedef struct _ZddxOperationsConfigFilterHelper_s
{
    ZWCSTR path;
    ZWWORD lenght;
} _ZddxOperationsConfigFilterHelper_t;

typedef struct _ZddxOperationsConfigCacheUseList_s
{
    ZWDWORD unique;
    ZTIME_T last_update;
    size_t size_file;
} _ZddxOperationsConfigCacheUseList_t;

typedef struct _ZddxOperationsConfigCacheUse_s
{
    size_t length;
    size_t max_length;
    _ZddxOperationsConfigCacheUseList_t list[];
} _ZddxOperationsConfigCacheUse_t;

ZWEXPORT_PRIVATE ZWError _zddx_operations_backup(const _ZddxOperationsConfigCtx_t *const ctx, const _ZStreamWriter_t *const stream, void *const ctx_stream, const _ZddxOperationsConfigFilterHelper_t *const filter, const size_t count);
ZWEXPORT_PRIVATE ZWError _zddx_operations_restore(_ZddxOperationsConfigCtx_t *const ctx, const _ZStreamReader_t *const stream, void *const ctx_stream, const _ZddxOperationsConfigFilterHelper_t *const filter, const size_t count, const ZWBOOL full);
ZWEXPORT_PRIVATE ZWError _zddx_operations_restore_read_config(const _ZddxOperationsConfigCtx_t *const ctx, void *const arg, ZEncoderDecoderStatus_t (*load_controller)(void *, ZDecoder_t *), ZEncoderDecoderStatus_t (*load_device)(void *, ZDecoder_t *, ZWDWORD));
static inline ZWBOOL _zddx_operations_is_restore_info(const _ZddxOperationsConfigCtx_t *const ctx)
{
    return ctx->restore_attributes.valid_type;
}
static inline void _zddx_operations_reset_restore_info(_ZddxOperationsConfigCtx_t *const ctx)
{
    ctx->restore_attributes.valid_type = FALSE;
}

ZWEXPORT_PRIVATE ZWError _zddx_operations_save_with_lock(const _ZddxOperationsConfigCtx_t *const ctx);
ZWEXPORT_PRIVATE ZWError _zddx_operations_delete_with_lock(_ZddxOperationsConfigCtx_t *const ctx);
ZWEXPORT_PRIVATE ZWError _zddx_operations_load(_ZddxOperationsConfigCtx_t *const ctx);
ZWEXPORT_PRIVATE ZWError _zddx_operations_save_device(const _ZddxOperationsConfigCtx_t *const ctx, const ZWDWORD id);
ZWEXPORT_PRIVATE ZWError _zddx_operations_save_controller(const _ZddxOperationsConfigCtx_t *const ctx);
ZWEXPORT_PRIVATE ZWError _zddx_operations_delete_device(const _ZddxOperationsConfigCtx_t *const ctx, const ZWDWORD id);

ZWEXPORT_PRIVATE ZWError _zddx_operations_init(_ZddxOperationsConfigCtx_t *const ctx, const ZDataRootObject data_root, ZWCSTR config_dir, const ZWCSTR prefix, const ZEncoderDecoderType_t type, const ZWBOOL separate, const _ZddxOperationsConfigFunctions_t *const functions, void *const arg);
ZWEXPORT_PRIVATE void _zddx_operations_deinit(_ZddxOperationsConfigCtx_t *const ctx);
static inline ZWBOOL _zddx_operations_is_loaded(const _ZddxOperationsConfigCtx_t *const ctx)
{
    return ctx->loaded;
}
static inline void _zddx_operations_reset_loaded_status(_ZddxOperationsConfigCtx_t *const ctx)
{
    ctx->loaded = FALSE;
}
static inline ZWCSTR _zddx_operations_get_config_dir(const _ZddxOperationsConfigCtx_t *const ctx)
{
    return ctx->config_dir;
}
static inline size_t _zddx_operations_get_length_config_dir(const _ZddxOperationsConfigCtx_t *const ctx)
{
    return ctx->length_config_dir;
}
static inline ZWLog _zddx_operations_get_log(const _ZddxOperationsConfigCtx_t *const ctx)
{
    return _zdata_root_get_log(ctx->data_root);
}
ZWEXPORT_PRIVATE ZWError _zddx_operations_file_open_tmp(const _ZddxOperationsConfigCtx_t *const ctx, ZW_FILE_HANDLE *const p_fd, ZWSTR *const p_path, const ZWDWORD mode);

#if defined(__ZWAY_STORAGE_VIA_FILE__)
ZWEXPORT_PRIVATE ZWError _zddx_operations_cache_create_path(const _ZddxOperationsConfigCtx_t *const ctx, const ZWWORD crc16, const size_t size, ZWSTR *const p_path);
ZWEXPORT_PRIVATE ZWDWORD _zddx_operations_cache_gen_path_unique(const ZWCSTR path);
ZWEXPORT_PRIVATE size_t _zddx_operations_cache_clean(const _ZddxOperationsConfigCtx_t *const ctx, _ZddxOperationsConfigCacheUse_t *const cache_use, const size_t n, const ZWBOOL force);
#endif

#endif//zddx_operations_private_h
